package ljl.bilibili.chat.ppt;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * API 认证算法类，用于生成签名。
 */
public class ApiAuthAlgorithm {

    /**
     * 获取给定 appId 和 secret 的签名。
     *
     * @param appId  用于生成签名的 appId。
     * @param secret 用于生成签名的密钥。
     * @param ts     时间戳。
     * @return 生成的签名。
     */
    public String getSignature(String appId, String secret, long ts) {
        try {
            // 生成 appId 和时间戳的 MD5 哈希值
            String auth = md5(appId + ts);
            // 使用生成的哈希值和密钥进行 HMAC SHA1 加密以生成签名
            return hmacSHA1Encrypt(auth, secret);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            // 打印异常堆栈信息以便调试
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 使用 HMAC SHA1 算法进行加密。
     *
     * @param encryptText 要加密的文本。
     * @param encryptKey  加密密钥。
     * @return 加密后的字符串。
     * @throws NoSuchAlgorithmException 如果指定的算法不可用。
     * @throws InvalidKeyException      如果密钥无效。
     */
    private String hmacSHA1Encrypt(String encryptText, String encryptKey)
            throws NoSuchAlgorithmException, InvalidKeyException {
        SecretKeySpec keySpec = new SecretKeySpec(
                encryptKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");

        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(keySpec);
        byte[] result = mac.doFinal(encryptText.getBytes(StandardCharsets.UTF_8));

        return Base64.encodeBase64String(result);
    }

    /**
     * 生成给定文本的 MD5 哈希值。
     *
     * @param text 要哈希的文本。
     * @return 文本的 MD5 哈希值。
     * @throws NoSuchAlgorithmException 如果 MD5 算法不可用。
     */
    private String md5(String text) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(text.getBytes(StandardCharsets.UTF_8));

        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
